use core::{cell::RefCell, ffi::c_void, mem::size_of, ptr::{null, null_mut}};

use alloc::{collections::LinkedList, sync::Arc};

use crate::{irq::{rt_hw_interrupt_disable, rt_hw_interrupt_enable}, mem::rt_malloc, rt_extern::RtErrCode, scheduler::{get_cur_thread, rt_schedule}, thread::*, timer::rt_timer_start};

use super::Ipc;

struct MyNode<T: Copy> 
{
    next_ptr: *mut MyNode<T>,
    data: T,
}


impl <T: Copy>MyNode<T> {

}

struct msg_queue<'a, T: Copy> {
    name: &'a str,

    msg_size: usize,
    max_msgs: usize, 

    head: *mut MyNode<T>,
    tail: *mut MyNode<T>,
    free_list: *mut MyNode<T>,
    len: usize,

    recv_suspend_list: LinkedList<Arc<RefCell<Thread>>>,
    // sender_suspend_list: LinkedList<Arc<RefCell<Thread>>>,
}

impl <'a, T: Copy> msg_queue<'a, T> {
    fn pop_freelist(&mut self) -> *mut MyNode<T> {
        if self.len == 0 {
            null_mut()
        } else {
            let p = self.free_list;
            self.free_list = unsafe {
                (*p).next_ptr
            };
            p
        }
    }

    fn push_freelist(&mut self, p: *mut MyNode<T>) {
        unsafe {
            (*p).next_ptr = self.free_list;
            self.free_list = p;
        }
    }

    pub fn new(name: &'a str, max_msgs: usize, ) -> Self {
        let size = size_of::<MyNode<T>>();

        let mut p = rt_malloc(size*max_msgs) as *mut MyNode<T>;

        unsafe {
            (*p).next_ptr = null_mut();
        }        

        let mut msgq = msg_queue {
            name,
            msg_size: size,
            max_msgs,

            head: null_mut(),
            tail: null_mut(),
            free_list: p,
            len: 0,

            recv_suspend_list: LinkedList::new(),
            // sender_suspend_list: LinkedList::new(),
        };

        // 初始化free_list
        for _i in 1..max_msgs {
            unsafe {
                p = p.offset(size as isize);
                msgq.push_freelist(p);
            }
        }
        msgq
    }

    pub fn send(&mut self, data: T) -> Result<(), RtErrCode> {

        let level = unsafe { rt_hw_interrupt_disable() };

        if self.len == self.max_msgs {
            unsafe { rt_hw_interrupt_enable(level) };
            return Err(RtErrCode::RtEfull);
        }

        self.len += 1;
        let p = self.pop_freelist();
        
        unsafe {
            (*p).data = data;
            (*p).next_ptr = null_mut();

            if self.head.is_null() {
                self.head = p;
            }

            if !self.tail.is_null() {
                (*self.tail).next_ptr = p;
            }
            self.tail = p; 
        }

        if let Some(thread) = self.recv_suspend_list.pop_front() {
            rt_thread_resume(thread);
            
            unsafe { rt_hw_interrupt_enable(level) };

            rt_schedule();

            return Ok(());
        } 
        
        unsafe { rt_hw_interrupt_enable(level) };

        Ok(())
    }

    pub fn recv(&mut self, mut timeout: isize) -> Result<T, RtErrCode> {
        let mut level = unsafe { rt_hw_interrupt_disable() };
        let data;

        let always_wait = if timeout < 0 {
            timeout = 20;
            true
        } else {
            false
        };

        // 无消息
        if self.len == 0 && timeout == 0 {
            unsafe {rt_hw_interrupt_enable(level) };
            
            return Err(RtErrCode::RtEtimeout);
        } 

        while self.len == 0 {
            let thread = get_cur_thread().unwrap();
            
            thread.borrow_mut().set_err(Ok(()));

            // 等到消息来为止
            
            let timer = thread.borrow_mut().timer.clone();

            timer.borrow_mut().set_tick(timeout as usize);

            rt_timer_start(timer);
            
            unsafe { rt_hw_interrupt_enable(level)};

            rt_schedule();

            level = unsafe { rt_hw_interrupt_disable() };

            let thread = get_cur_thread().unwrap();

            if !always_wait && thread.borrow().err().is_err() {

                unsafe { rt_hw_interrupt_enable(level)};

                return Err(thread.borrow().err().unwrap_err());
            }       
        }

        // 有消息
        let p = self.head;

        unsafe {
            self.head = (*p).next_ptr;

            if self.tail == p {
                self.tail = null_mut();
            }

            data = (*p).data;
        }
        
        unsafe {rt_hw_interrupt_enable(level) };
        Ok(data)
    }

    fn suspend_recv(&mut self, thread: Arc<RefCell<Thread>>) {
        
        self.recv_suspend_list.push_back(thread.clone());

        rt_thread_suspend(thread).unwrap_or(());
    }
}

// impl <'a, T>Ipc for msg_queue<'a, T> {
//     fn ipc_suspend(&mut self, thread: Arc<RefCell<Thread>>) {
//         rt_thread_suspend(thread.clone()).unwrap_or(());
//         self.lis
//     }

//     fn ipc_list_resume(&mut self) {
        
//     }

//     fn ipc_list_resume_all(&mut self) {
        
//     }
// }
